using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;

namespace OrigPacman
{
    public enum Direction { NORTH, SOUTH, EAST, WEST, STOP };

    class Map
    {
        #region Variables
        Texture2D background;
        Texture2D point;
        List<Waypoint> waypoints;
        List<Pellet> pelletList;
        StreamReader file;
        long frameCount = 0;
        long pressed = 0;
        bool drawWaypoints = false;
        Texture2D bigPellet;
        Texture2D smallPellet;
        Texture2D fruit;
        float superTimeStart = 7.0f;

        protected Rectangle container;
        protected Vector2 position;
        protected int width;
        protected int height;
        protected bool complete;
        protected SpriteFont font;
        #endregion

        #region Constants
        public const int BIG_POINTS = 50;
        public const int REGULAR_POINTS = 10;
        public const int FRUIT_POINTS = 200;
        public const string LevelFileName = "../../../level1.txt";
        private const int MapWidth = 512;
        #endregion

        #region Properties
        public Rectangle Bounds
        {
            get { return container; }
            set
            {
                container = value;
                position = new Vector2(container.X, container.Y);
            }
        }
        public Vector2 Position
        {
            get { return position; }
            set
            {
                position = value;
                container.X = (int)position.X;
                container.Y = (int)position.Y;
            }
        }
        public int Width
        {
            get { return width; }
            set { width = value; }
        }
        public int Height
        {
            get { return height; }
            set { height = value; }
        }
        public bool Complete
        {
            get { return complete; }
            set { complete = value; }
        }
        public List<Pellet> PelletList
        {
            get { return pelletList; }
            set { pelletList = value; }
        }
        public List<Waypoint> WaypointList
        {
            get { return waypoints; }
            set { waypoints = value; }
        }
        #endregion

        public Map(GraphicsDevice device)
        {
            width = MapWidth;
            height = MapWidth;
            container = new Rectangle(45, 45, width, height);
            pelletList = new List<Pellet>();
            LoadLevel1();
        }

        public void LoadContent(ContentManager content)
        {
            background = content.Load<Texture2D>("images/background1");
            point = content.Load<Texture2D>("images/point");
            bigPellet = content.Load<Texture2D>("images/pellet");
            smallPellet = content.Load<Texture2D>("images/smallPellet");
            fruit = content.Load<Texture2D>("images/apple");
            font = content.Load<SpriteFont>("Times New Roman");
            setupPellets();
        }

        public void Update(float elapsed, Pacman pacman)
        {
            if (pelletList.Count == 0)
            {
                complete = true;
            }
            else
            {
                CheckPelletCollision(pacman);
            }
        }

        public void Render(ref SpriteBatch sprite)
        {
            frameCount++;
            if (KeyPress.KeyPressGame.KeyPressedThisFrame(Keys.F1) && pressed < frameCount-5)
            {
                pressed = frameCount;
                drawWaypoints = !drawWaypoints;
            }
            sprite.Draw(background, container, Color.White);

            if (drawWaypoints)
            {

                foreach (Waypoint waypoint in waypoints)
                {
                    sprite.Draw(point, waypoint.Bounds, Color.White);
                    //sprite.DrawString(font, a.East.ToString(), a.Position, Color.White);
                }
            }

            foreach (Pellet pellet in pelletList)
            {
                sprite.Draw(pellet.Texture, pellet.Bounds, Color.White);
            }
        }

        private void LoadLevel1()
        {
            int wpOffset = 45;
            file = new StreamReader(LevelFileName);
            Waypoint currentWaypoint = new Waypoint();
            waypoints = new List<Waypoint>();
            currentWaypoint.West = 8;
            currentWaypoint.East = 47;
            currentWaypoint.Position = new Vector2(289, 366);
            waypoints.Add(currentWaypoint);
            
            string nextString = file.ReadLine();
            if (nextString.Contains("Waypoint"))
            {
                while (nextString != "END")
                {
                    //Reset all positions
                    currentWaypoint = new Waypoint();
                    if (nextString.Contains("Vector"))
                    {
                        int x, y;
                        int beginningOfX = nextString.IndexOf('x') + 1;
                        int beginningOfY = nextString.IndexOf('y', beginningOfX) + 1;

                        x = Convert.ToInt32(nextString.Substring(beginningOfX, beginningOfY - beginningOfX - 1));
                        y = Convert.ToInt32(nextString.Substring(beginningOfY));
                        currentWaypoint.Position = new Vector2(x + wpOffset, y + wpOffset);
                    }
                    nextString = file.ReadLine();
                    int nextNode = 0;
                    while (!nextString.Contains("Waypoint") && nextString != "END")
                    {
                        if (nextString.Contains("Up"))
                        {
                            nextNode = Convert.ToInt32(nextString.Substring(3));
                            currentWaypoint.North = nextNode;
                        }
                        if (nextString.Contains("Down"))
                        {
                            nextNode = Convert.ToInt32(nextString.Substring(5));
                            currentWaypoint.South = nextNode;
                        }
                        if (nextString.Contains("Left"))
                        {
                            nextNode = Convert.ToInt32(nextString.Substring(5));
                            currentWaypoint.West = nextNode;
                        }
                        if (nextString.Contains("Right"))
                        {
                            nextNode = Convert.ToInt32(nextString.Substring(6));
                            currentWaypoint.East = nextNode;
                        }
                        nextString = file.ReadLine();
                    }
                    waypoints.Add(currentWaypoint);
                }
            }
            file.Close();
        }

        public List<Waypoint> Waypoints 
        {
            get { return waypoints; }
            set { waypoints = value; }
        }

        public Pellet MakePellet(int points, Vector2 v)
        {
            Pellet pellet = new Pellet();
            pellet.Points = points;

            switch (points)
            {
                case BIG_POINTS:
                    if (bigPellet != null)
                    {
                        pellet.Texture = bigPellet;
                    }
                    pellet.Super = true;
                    break;
                case REGULAR_POINTS:
                    if (smallPellet != null)
                    {
                        pellet.Texture = smallPellet;
                    }
                    break;
                default:
                    if (fruit != null)
                    {
                        pellet.Texture = fruit;
                    }
                    break;
            }
            pellet.Position = v;
            return pellet;
        }

        private void setupPellets()
        {
            // Super pellets and fruit
            pelletList.Add(MakePellet(BIG_POINTS, new Vector2(65, 65)));
            pelletList.Add(MakePellet(BIG_POINTS, new Vector2(512, 65)));
            pelletList.Add(MakePellet(BIG_POINTS, new Vector2(65, 512)));
            pelletList.Add(MakePellet(BIG_POINTS, new Vector2(512, 512)));
            pelletList.Add(MakePellet(FRUIT_POINTS, new Vector2(512, 480)));

            //Create regularPellets;
            for (int i = 0; i < 13; i++)
            {
                pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2(65, (i * 32) + 97)));
                /// added this check, so that a pellet would not be drawn
                /// over the fruit
                if (i != 12)
                {
                    pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2(512, (i * 32) + 97)));
                }
                pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 32) + 97, 512)));
                pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 101, 370)));
                pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 101, 418)));
                pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 101, 466)));
                
                if (i > 0 && i < 12)
                {
                    pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 101, 322)));
                }
                if (i > 0 && i < 12)
                {
                    pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 101, 114)));
                }
                if (i < 3 || (i > 3 && i < 9) || i > 9)
                {
                    pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 101, 66)));
                }
                if (i > 2 && i < 10)
                {
                    pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 101, 162)));
                }
                if (i < 4)
                {
                    pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 242, 210)));

                    if (i == 0 || i == 3)
                    {
                        pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 242, 247)));
                        pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 242, 284)));
                    }
                }
                if ((i > 1 && i < 4) ||( i > 8 && i < 11) || i == 6)
                {
                    pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 101, 274)));
                }
                if ((i > 1 && i < 4) || (i > 8 && i < 11))
                {
                    pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2((i * 31) + 101, 226)));
                }
                if (i < 6)
                {
                    pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2(110, (i * 31) + 140)));
                    pelletList.Add(MakePellet(REGULAR_POINTS, new Vector2(465, (i * 31) + 140)));
                }       
            }
        }

        public void CheckPelletCollision(Pacman pacman)
        {
            int index = -1;
            foreach (Pellet pellet in pelletList)
            {
                Point centerOfPellet = new Point((int) (pellet.Position.X + pellet.Bounds.Width / 2),
                    (int) (pellet.Position.Y + pellet.Bounds.Height / 2));
                if (pacman.Bounds.Contains(centerOfPellet))
                {
                    index = pelletList.IndexOf(pellet);
                    pacman.Score += pellet.Points;
                    if (pellet.Super)
                    {
                        pacman.Super = true;
                        pacman.SuperTime += superTimeStart;
                        pacman.Sounds.PlayCue("supermode");
                    }
                    else if (pellet.Points == FRUIT_POINTS)
                    {
                        pacman.Sounds.PlayCue("fruit");
                    }
                    else
                    {
                        pacman.Sounds.PlayCue("chomp");

                    }
                    break;
                }
            }
            if (index != -1)
            {
                pelletList.RemoveAt(index);
                if (pelletList.Count == 0)
                {
                    Complete = true;
                }
            }
        }
    }
}

